--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
sbapp/pyogg/vorbis_file.py 0.9.2 (695cf253) Text, 5.48 KB
Tff7b72import T7ee787ctypes
Tff7b72from T7ee787. Tff7b72import Te6edf3vorbis
Tff7b72from T7ee787.T7ee787audio_file Tff7b72import Te6edf3AudioFile
Tff7b72from T7ee787.T7ee787pyogg_error Tff7b72import Te6edf3PyOggError
T8b949e# TODO: Issue #70: Vorbis files with multiple logical bitstreams could
T8b949e# be supported by chaining VorbisFile instances (with say a 'next'
T8b949e# attribute that points to the next VorbisFile that would contain the
T8b949e# PCM for the next logical bitstream). A considerable constraint to
T8b949e# implementing this was that examples files that demonstrated multiple
T8b949e# logical bitstreams couldn't be found or created. Note that even
T8b949e# Audacity doesn't handle multiple logical bitstreams (see
T8b949e# https://wiki.audacityteam.org/wiki/OGG#Importing_multiple_stream_files).
T8b949e# TODO: Issue #53: Unicode file names are not well supported.
T8b949e# They may work in macOS and Linux, they don't work under Windows.
Tff7b72class T56d364VorbisFileTb4b4b4(Te6edf3AudioFileTb4b4b4)Tb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4,
Te6edf3pathTb4b4b4: Tffa657strTb4b4b4,
Te6edf3bytes_per_sampleTb4b4b4: Tffa657int Tff7b72= T79c0ff2Tb4b4b4,
Te6edf3signedTb4b4b4:Tffa657bool Tff7b72= Tff7b72TrueTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Load an OggVorbis File.
path specifies the location of the Vorbis file. Unicode
filenames may not work correctly under Windows.
bytes_per_sample specifies the word size of the PCM. It may
be either 1 or 2. Specifying one byte per sample will save
memory but will likely decrease the quality of the decoded
audio.
Only Vorbis files with a single logical bitstream are
supported.
"""
T8b949e# Sanity check the number of bytes per sample
Tff7b72assert Te6edf3bytes_per_sampleTff7b72==T79c0ff1 Tff7b72or Te6edf3bytes_per_sampleTff7b72==T79c0ff2
T8b949e# Sanity check that the vorbis library is available (for mypy)
Tff7b72assert Te6edf3vorbisTff7b72.Td2a8fflibvorbisfile Tff7b72is Tff7b72not Tff7b72None
T8b949e#: Bytes per sample
Tff7b72selfTff7b72.Td2a8ffbytes_per_sample Tff7b72= Te6edf3bytes_per_sample
T8b949e#: Samples are signed (rather than unsigned)
Tff7b72selfTff7b72.Td2a8ffsigned Tff7b72= Te6edf3signed
T8b949e# Create a Vorbis File structure
Te6edf3vf Tff7b72= Te6edf3vorbisTff7b72.Td2a8ffOggVorbis_FileTb4b4b4(Tb4b4b4)
T8b949e# Attempt to open the Vorbis file
Te6edf3error Tff7b72= Te6edf3vorbisTff7b72.Td2a8fflibvorbisfileTff7b72.Td2a8ffov_fopenTb4b4b4(
Te6edf3vorbisTff7b72.Td2a8ffto_char_pTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4,
Te6edf3ctypesTff7b72.Td2a8ffbyrefTb4b4b4(Te6edf3vfTb4b4b4)
Tb4b4b4)
T8b949e# Check for errors during opening
Tff7b72if Te6edf3error Tff7b72!= T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Tb4b4b4(Ta5d6ff"Ta5d6ffFile Ta5d6ff'Tffd700{}Ta5d6ff'Ta5d6ff couldnTa5d6ff'Ta5d6fft be opened or doesnTa5d6ff'Ta5d6fft exist. Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffError code : Tffd700{}Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3errorTb4b4b4)
Tb4b4b4)
T8b949e# Extract info from the Vorbis file
Te6edf3info Tff7b72= Te6edf3vorbisTff7b72.Td2a8fflibvorbisfileTff7b72.Td2a8ffov_infoTb4b4b4(
Te6edf3ctypesTff7b72.Td2a8ffbyrefTb4b4b4(Te6edf3vfTb4b4b4)Tb4b4b4,
Tff7b72-T79c0ff1 T8b949e# the current logical bitstream
Tb4b4b4)
T8b949e#: Number of channels in audio file.
Tff7b72selfTff7b72.Td2a8ffchannels Tff7b72= Te6edf3infoTff7b72.Td2a8ffcontentsTff7b72.Td2a8ffchannels
T8b949e#: Number of samples per second (per channel), 44100 for
T8b949e# example.
Tff7b72selfTff7b72.Td2a8fffrequency Tff7b72= Te6edf3infoTff7b72.Td2a8ffcontentsTff7b72.Td2a8ffrate
T8b949e# Extract the total number of PCM samples for the first
T8b949e# logical bitstream
Te6edf3pcm_length_samples Tff7b72= Te6edf3vorbisTff7b72.Td2a8fflibvorbisfileTff7b72.Td2a8ffov_pcm_totalTb4b4b4(
Te6edf3ctypesTff7b72.Td2a8ffbyrefTb4b4b4(Te6edf3vfTb4b4b4)Tb4b4b4,
T79c0ff0 T8b949e# to extract the length of the first logical bitstream
Tb4b4b4)
T8b949e# Create a memory block to store the entire PCM
Te6edf3Buffer Tff7b72= Tb4b4b4(
Te6edf3ctypesTff7b72.Td2a8ffc_char
Tff7b72* Tb4b4b4(
Te6edf3pcm_length_samples
Tff7b72* Tff7b72selfTff7b72.Td2a8ffbytes_per_sample
Tff7b72* Tff7b72selfTff7b72.Td2a8ffchannels
Tb4b4b4)
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffbuffer Tff7b72= Te6edf3BufferTb4b4b4(Tb4b4b4)
T8b949e# Create a pointer to the newly allocated memory. It
T8b949e# seems we can only do pointer arithmetic on void
T8b949e# pointers. See
T8b949e# https://mattgwwalker.wordpress.com/2020/05/30/pointer-manipulation-in-python/
Te6edf3buf_ptr Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffcastTb4b4b4(
Te6edf3ctypesTff7b72.Td2a8ffpointerTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbufferTb4b4b4)Tb4b4b4,
Te6edf3ctypesTff7b72.Td2a8ffc_void_p
Tb4b4b4)
T8b949e# Storage for the index of the logical bitstream
Te6edf3bitstream_previous Tff7b72= Tff7b72None
Te6edf3bitstream Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffc_intTb4b4b4(Tb4b4b4)
T8b949e# Set bytes remaining to read into PCM
Te6edf3read_size Tff7b72= Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbufferTb4b4b4)
Tff7b72while Tff7b72TrueTb4b4b4:
T8b949e# Convert buffer pointer to the desired type
Te6edf3ptr Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffcastTb4b4b4(
Te6edf3buf_ptrTb4b4b4,
Te6edf3ctypesTff7b72.Td2a8ffPOINTERTb4b4b4(Te6edf3ctypesTff7b72.Td2a8ffc_charTb4b4b4)
Tb4b4b4)
T8b949e# Attempt to decode PCM from the Vorbis file
Te6edf3result Tff7b72= Te6edf3vorbisTff7b72.Td2a8fflibvorbisfileTff7b72.Td2a8ffov_readTb4b4b4(
Te6edf3ctypesTff7b72.Td2a8ffbyrefTb4b4b4(Te6edf3vfTb4b4b4)Tb4b4b4,
Te6edf3ptrTb4b4b4,
Te6edf3read_sizeTb4b4b4,
T79c0ff0Tb4b4b4, T8b949e# Little endian
Tff7b72selfTff7b72.Td2a8ffbytes_per_sampleTb4b4b4,
Tffa657intTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsignedTb4b4b4)Tb4b4b4,
Te6edf3ctypesTff7b72.Td2a8ffbyrefTb4b4b4(Te6edf3bitstreamTb4b4b4)
Tb4b4b4)
T8b949e# Check for errors
Tff7b72if Te6edf3result Tff7b72< T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffAn error occurred decoding the Vorbis file: Ta5d6ff"Tff7b72+
Ta5d6fffTa5d6ff"Ta5d6ffError code: Tffd700{Te6edf3resultTffd700}Ta5d6ff"
Tb4b4b4)
T8b949e# Check that the bitstream hasn't changed as we only
T8b949e# support Vorbis files with a single logical bitstream.
Tff7b72if Te6edf3bitstream_previous Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3bitstream_previous Tff7b72= Te6edf3bitstream
Tff7b72elseTb4b4b4:
Tff7b72if Te6edf3bitstream_previous Tff7b72!= Te6edf3bitstreamTb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffPyOgg currently supports Vorbis files Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffwith only one logical streamTa5d6ff"
Tb4b4b4)
T8b949e# Check for end of file
Tff7b72if Te6edf3result Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72break
T8b949e# Calculate the number of bytes remaining to read into PCM
Te6edf3read_size Tff7b72-Tff7b72= Te6edf3result
T8b949e# Update the pointer into the buffer
Te6edf3buf_ptrTff7b72.Td2a8ffvalue Tff7b72+Tff7b72= Te6edf3result
T8b949e# Close the file and clean up memory
Te6edf3vorbisTff7b72.Td2a8fflibvorbisfileTff7b72.Td2a8ffov_clearTb4b4b4(Te6edf3ctypesTff7b72.Td2a8ffbyrefTb4b4b4(Te6edf3vfTb4b4b4)Tb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────